#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Ticker.h>
#define LED1_BUILTIN 12
#define LED2_BUILTIN 13
 
// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "Y1415";
const char* password = "y14151415";
const char* mqttServer = "111.230.201.180";
Ticker ticker;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
 int count;    // Ticker计数用变量
// ****************************************************
// 注意！以下需要用户根据平台信息进行修改！否则无法工作!
// ****************************************************
const char* mqttUserName = "iot";         // 服务端连接用户名(需要修改)
const char* mqttPassword = "iot123456";          // 服务端连接密码(需要修改)
const char* clientId = "XingHuan_3_id";          // 客户端id (需要修改)
const char* subTopic = "XingHuan/curtain_kz";        // 订阅主题(需要修改)
const char* pubTopic = "XingHuan/curtain_ld";        // 发布主题(需要修改)
const char* pub1Topic = "XingHuan/curtain_ydz";        // 发布主题(需要修改)
const char* willTopic = "XingHuan/curtain_yz";       // 遗嘱主题名称(需要修改)
// ****************************************************
 
//遗嘱相关信息
const char* willMsg = "curtain offline";        // 遗嘱主题信息
const int willQos = 0;                          // 遗嘱QoS
const int willRetain = true;                   // 遗嘱保留
 
const int subQoS = 1;            // 客户端订阅主题时使用的QoS级别（截止2020-10-07，仅支持QoS = 1，不支持QoS = 2）
const bool cleanSession = false; // 清除会话（如QoS>0必须要设为false）
 
bool ledStatus = LOW;
void setup() {
  pinMode(LED1_BUILTIN, OUTPUT);          // 设置板上LED引脚为输出模式
    pinMode(LED2_BUILTIN, OUTPUT);          // 设置板上LED引脚为输出模式
  digitalWrite(LED1_BUILTIN, ledStatus);  // 启动后关闭板上LED
   digitalWrite(LED2_BUILTIN, ledStatus);  // 启动后关闭板上LED
  Serial.begin(9600);                    // 启动串口通讯

  //设置ESP8266工作模式为无线终端模式
  WiFi.mode(WIFI_STA);
  
  // 连接WiFi
  connectWifi();
  
  // 设置MQTT服务器和端口号
  mqttClient.setServer(mqttServer, 1883);
  mqttClient.setCallback(receiveCallback);  //回调函数
 
  // 连接MQTT服务器
  connectMQTTserver();
  // Ticker定时对象
  ticker.attach(1, tickerCount); 
}
 
void loop() {
  // 如果开发板未能成功连接服务器，则尝试连接服务器
  if (!mqttClient.connected()) {
    connectMQTTserver();
  }

  // 每隔3秒钟发布一次信息
//    if (count >= 1){
//      pubMQTTmsg();
//      count = 0;
//    }  
   // 处理信息以及心跳
   mqttClient.loop();
   
}
 
// 连接MQTT服务器并订阅信息
void connectMQTTserver(){
  // 根据ESP8266的MAC地址生成客户端ID（避免与其它ESP8266的客户端ID重名）
  
  /* 连接MQTT服务器
  boolean connect(const char* id, const char* user, 
                  const char* pass, const char* willTopic, 
                  uint8_t willQos, boolean willRetain, 
                  const char* willMessage, boolean cleanSession); 
  若让设备在离线时仍然能够让qos1工作，则connect时的cleanSession需要设置为false                
                  */
  if (mqttClient.connect(clientId, mqttUserName, 
                         mqttPassword, willTopic, 
                         willQos, willRetain, willMsg, cleanSession)) { 
//    Serial.print("MQTT Server Connected. ClientId: ");
//    Serial.println(clientId);
//    Serial.print("MQTT Server: ");
//    Serial.println(mqttServer);
    willMsg = "curtain online";    
    mqttClient.publish(willTopic, willMsg);
    subscribeTopic(); // 订阅指定主题
  } else {
//    Serial.print("MQTT Server Connect Failed. Client State:");
//    Serial.println(mqttClient.state());
    delay(5000);
  }   
}
 
// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {
//  Serial.print("Message Received [");
//  Serial.print(topic);
//  Serial.print("] ");
 // for (int i = 0; i < length; i++) {
//    Serial.print((char)payload[i]);
//  }
//  Serial.println("");
//  Serial.print("Message Length(Bytes) ");
//  Serial.println(length);
 
  if ((char)payload[0] == '0') {     // 如果收到的信息以“0”为开始

    ledStatus = HIGH;
    digitalWrite(LED1_BUILTIN, ledStatus);  // 则点亮LED。
digitalWrite(LED2_BUILTIN, LOW); // 否则熄灭LED。
Serial.print("On\r\n");
  } else if((char)payload[0] == '1'){

    ledStatus = HIGH;                 
    digitalWrite(LED1_BUILTIN, LOW); // 否则熄灭LED。          
    digitalWrite(LED2_BUILTIN, ledStatus); // 否则熄灭LED。
    Serial.print("Off\r\n");
  }else if((char)payload[0] == '2'){

    ledStatus = HIGH;                           
    digitalWrite(LED1_BUILTIN, ledStatus); // 否则熄灭LED。
    digitalWrite(LED2_BUILTIN, ledStatus); // 否则熄灭LED。
    Serial.print("Auto\r\n");
  }
}
 
// 订阅控制主题
void subscribeTopic(){
 
  // 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
  // 请注意subscribe函数第二个参数数字为QoS级别。这里为QoS = 1
  if(mqttClient.subscribe(subTopic, subQoS)){
//    Serial.print("Subscribed Topic: ");
//    Serial.println(subTopic);
  } else {
//    Serial.print("Subscribe Fail...");
  }  
}
// 发布信息
void pubMQTTmsg(){
String serialData = Serial.readString();
//char* publishMsg=(char*)(serialData.c_str());
  char publishMsg[serialData.length() + 1];   
  strcpy(publishMsg, serialData.c_str());


StaticJsonDocument<2000> doc;

DeserializationError error = deserializeJson(doc, publishMsg);



int rain_value = doc["rain_value"]; // 3
int light_value = doc["light_value"]; // 72
const char* rain = std::to_string(rain_value).c_str();
const char* light = std::to_string(light_value).c_str();

 //实现ESP8266向主题发布信息
  
    mqttClient.publish(pubTopic, light);
    //Serial.println("Publish Topic:");Serial.println(pubTopic);
   //Serial.println("Publish ISBN message:");Serial.println(publishMsg); 

    mqttClient.publish(pub1Topic,rain);
    //Serial.println("Message Publish Failed."); 
  
}
 void tickerCount(){
  count++;
}
// ESP8266连接wifi
void connectWifi(){
 
  WiFi.begin(ssid, password);
 
  //等待WiFi连接,成功连接后输出成功信息
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  //  Serial.print(".");
  }
//  Serial.println("");
//  Serial.println("WiFi Connected!");  
//  Serial.println(""); 
}
